package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.constant.EsNormalConstant;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaymentSheetTypeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.GaodeGeoHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.fund.enums.ModelTypeEnum;
import com.xbongbong.pro.service.toolbox.statistic.help.SystemChartHelp;
import com.xbongbong.pro.sheet.pojo.AmountDetailGetPojo;
import com.xbongbong.pro.sheet.pojo.vo.HandleLinkInfoVO;
import com.xbongbong.pro.user.pojo.UserTypePojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.PaymentBalanceInsertConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceUserEntity;
import com.xbongbong.saas.domain.entity.PaymentSheetUserEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.model.ContractUserModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PaymentBalanceModel;
import com.xbongbong.saas.model.PaymentBalanceUserModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.PaymentSheetUserModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author: 汪腾伟
 * @date: Created in 2021/9/7 19:53
 * @description： 适配工作流这边关于回款单的帮助类
 */
@Component
public class SaasPaymentSheetHelper {

    @Resource
    private SystemChartHelp systemChartHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private PaymentBalanceModel paymentBalanceModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private PaymentBalanceUserModel paymentBalanceUserModel;
    @Resource
    private ContractUserModel contractUserModel;
    @Resource
    private PaymentSheetUserModel paymentSheetUserModel;

    private static final Logger LOG = LoggerFactory.getLogger(GaodeGeoHelper.class);


    public Map<String, Double> handleRedSheetsBySheet(String corpid, Long sheetId, AmountDetailGetPojo amountDetailGetPojo) throws XbbException {
        // 查询该应收款下面关联的所有回款单(因为这个redsheet没有约定好，这里需要重复查询)
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder4LinkRed(corpid, Collections.singletonList(sheetId));
        List<String> fieldList = Arrays.asList(BasicConstant.ID, BasicConstant.DATAID, FieldTypeEnum.SHEET_ALONE.getAlias(), FieldTypeEnum.SHEET_UUID.getAlias(), PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.PAYMENT_SHEET_TYPE), PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.AMOUNT), PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.WRITE_OFF_AMOUNT), PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.CONTRACT), PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.PAYMENT));
        //分页查询
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = esHelper.findByPage(IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList, BasicConstant.ONE, EsNormalConstant.FIND_NUM, null);
        List<PaasFormDataEntityExt> sheetList = new ArrayList<>();
        if (esEntities != null) {
            sheetList = esEntities.getContent();
        }
        Set<String> uuidSet = new HashSet<>();
        /**
         key：红冲回款单的合同id_应收款id
         value：红冲单据的金额
         */
        Map<String, Double> redCidPidAmountMap = new HashMap<>(sheetList.size());
        Double sumAmount = 0D;
        for (PaasFormDataEntityExt entityExt : sheetList) {
            JSONObject data = entityExt.getData();
            String paymentSheetType = FastJsonHelper.getStringFromFormData(data, PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr());
            double sheetAmount = FundHelp.getSheetAmount4PaymentSheet(data, paymentSheetType);
            sumAmount = Arith.add(sumAmount, sheetAmount);
            if (Objects.equals(entityExt.getAlone(), SheetAloneEnum.NORMAL.getCode())) {
                fundHelp.formatCidPidRedAmountMap(PaymentSheetEnum.CONTRACT.getAttr(), PaymentSheetEnum.PAYMENT.getAttr(), redCidPidAmountMap, entityExt, sheetAmount);
                continue;
            } else {
                //父单，则读取子单
                uuidSet.add(entityExt.getUuid());
            }
        }
        amountDetailGetPojo.setRedAmount(sumAmount);
        //如果有明细，则处理明细
        List<PaasFormDataEntityExt> childList = fundHelp.getChildEsDataListByParentUuids(XbbRefTypeEnum.PAYMENT_SHEET, corpid, uuidSet, null, null);
        for (PaasFormDataEntityExt entityExt : childList) {
            JSONObject data = entityExt.getData();
            String paymentSheetType = FastJsonHelper.getStringFromFormData(data, PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr());
            double sheetAmount = FundHelp.getSheetAmount4PaymentSheet(data, paymentSheetType);
            fundHelp.formatCidPidRedAmountMap(PaymentSheetEnum.CONTRACT.getAttr(), PaymentSheetEnum.PAYMENT.getAttr(), redCidPidAmountMap, entityExt, sheetAmount);
        }
        amountDetailGetPojo.setRedCidPidAmountMap(redCidPidAmountMap);
        return redCidPidAmountMap;
    }


    public double sumRedAmountBySheet(String corpid, Long sheetId) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder4LinkRed(corpid, Collections.singletonList(sheetId));
        boolQueryBuilder.filter(termsQuery(StringConstant.FLOW_STATUS, Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        //聚合得到该条回款单（sheetId）关联的已红冲回款单总额
        //由于红冲预收款核销(退到余额)只有核销金额，因此汇总核销金额 ---  红冲预收款余额只有回款金额，但是此方法用到的地方不统计红冲预收款余额也可以
        return systemChartHelp.getDouble4Total(IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET, boolQueryBuilder, PaymentSheetEnum.getAttrConnectData(PaymentSheetEnum.WRITE_OFF_AMOUNT));
    }

    /**
     * 原始回款单的关联红冲回款单的查询条件
     * @param corpid 公司id
     * @param sheetIdIn 原单id集合
     * @return org.elasticsearch.index.query.BoolQueryBuilder
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private BoolQueryBuilder getBoolQueryBuilder4LinkRed(String corpid, List<Long> sheetIdIn) {
        // 查询该应收款下面关联的所有回款单(因为这个redsheet没有约定好，这里需要重复查询)
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.PASS.getType(), FlowStatusEnum.NOT_NEED_APPROVAL.getType())));
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        //限制alone
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.SHEET_ALONE.getAlias(), SheetAloneEnum.getNotChildCodeList()));
        //限制关联原始回款单id为sheetId
        boolQueryBuilder.filter(termsQuery(PaymentSheetEnum.getEsAttr4Keyword(PaymentSheetEnum.RED_SHEET), sheetIdIn));
        //只读红冲类型回款单
        boolQueryBuilder.filter(termsQuery(PaymentSheetEnum.getEsAttr4Keyword(PaymentSheetEnum.PAYMENT_SHEET_TYPE), PaymentSheetTypeEnum.getRedCodeList()));
        return boolQueryBuilder;
    }

    /**
     * 插入子回款单，并置父回款单的alone值
     * （1）金额大于0的明细超过1条，才会加子回款单，且才会把子回款单的合同、回款、归属人信息合并置入父回款单
     * （2）金额大于0的明细只有1条，没必要再存一条子回款单（详情展示时，会特殊处理alone=1的，把父本身模拟出一条子明细）
     *
     * @param corpid 公司id
     * @param sonPaymentSheetDataList 子回款单数据data list
     * @param paymentSheetEntityExt 父回款单实体
     * @param uuid 同分组uuid
     * @param paymentLinkInfoVO 应收款相关信息，如所属模式类型
     * @return java.util.List<com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt>
     * @throws XbbException
     * @author zcp
     * @date 19/11/21 021 21:38
     * @update 19/11/21 021 21:38
     * @since v1.0
     * @version v1.0
     */
    public List<PaymentSheetEntityExt> savePaymentSheetSon(String corpid, List<JSONObject> sonPaymentSheetDataList, PaymentSheetEntityExt paymentSheetEntityExt, String uuid, HandleLinkInfoVO paymentLinkInfoVO) throws XbbException {
        List<PaymentSheetEntityExt> sonPaymentSheetList = new ArrayList<>();
        try {
            /**
             金额大于0的明细超过1条，才会加子回款单，且才会把子回款单的合同、回款、归属人信息合并置入父回款单
             金额大于0的明细只有1条，没必要再存一条子回款单（详情展示时，会特殊处理alone=1的，把父本身模拟出一条子明细）
             */
            if (sonPaymentSheetDataList.size() > BasicConstant.ONE) {
                String sonSerialNo = paymentSheetEntityExt.getSerialNo() + SymbolConstant.POINT_ENGLISH;
                //应收款id - 应收款所属模式
                Map<Long, Long> idModelTypeMap = paymentLinkInfoVO.getIdModelTypeMap();
                //子回款单的批量新增
                for (int i = 1; i <= sonPaymentSheetDataList.size(); i++) {
                    JSONObject sonData = sonPaymentSheetDataList.get(i - 1);
                    PaymentSheetEntityExt sonPaymentSheetEntityExt = new PaymentSheetEntityExt();
                    if (sonData != null) {
                        sonData.remove(PaasConstant.REFUND_ID);
                        FormDataUtil.removeSystemData(sonData);
                    }
                    JSONArray linkIdStr = FastJsonHelper.getJsonArrFromFormData(sonData, PaymentSheetEnum.PAYMENT.getAttr());
                    List<Long> idList = JsonHelperUtil.parseArray(JSONArray.toJSONString(linkIdStr), Long.class);
                    //处理modelType
                    Long modelType = paymentSheetEntityExt.getSysLong10();
                    if (CollectionsUtil.isNotEmpty(idList) && idList.size() > 0) {
                        Long paymentId = idList.get(0);
                        //处理modelType
                        modelType = idModelTypeMap.getOrDefault(paymentId, ModelTypeEnum.PLAN.getCode());
                    }
                    BeanUtil.copyProperties(paymentSheetEntityExt, sonPaymentSheetEntityExt);
                    sonPaymentSheetEntityExt.setAlone(SheetAloneEnum.CHILD.getCode());
                    sonPaymentSheetEntityExt.setUuid(uuid);
                    sonPaymentSheetEntityExt.setData(sonData);
                    sonPaymentSheetEntityExt.setSerialNo(sonSerialNo + i);
                    sonPaymentSheetEntityExt.setSysLong10(modelType);
                    sonPaymentSheetList.add(sonPaymentSheetEntityExt);
                }
                if(!sonPaymentSheetList.isEmpty()){
                    paymentSheetModel.insertBatch(sonPaymentSheetList);
                }
            }
        }catch (Exception e) {
            for (PaymentSheetEntityExt sheetEntityExt : sonPaymentSheetList) {
                paasFormSubDataModel.transferSubForm(sheetEntityExt, IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET_SUB);
            }
            LOG.error("保存回款单明细到数据库报错", e);
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208053, PaymentErrorCodeEnum.API_ERROR_208053.getMsg(), XbbRefTypeEnum.PAYMENT_SHEET.getName());
        }
        return sonPaymentSheetList;
    }

    /**
     * 预收款余额保存
     *
     * @param paymentSheetEntityExt
     * @param distributorMark
     * @throws XbbException
     */
    public void saveByPaymentSheet(PaymentSheetEntityExt paymentSheetEntityExt, Integer distributorMark) throws XbbException {
        try {
            JSONObject data = paymentSheetEntityExt.getData();
            String paymentSheetTypeStr = data.getString(PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr());
            PaymentSheetTypeEnum paymentSheetTypeEnum = PaymentSheetTypeEnum.getByCode(paymentSheetTypeStr);
            Double advancePaymentBalance;
            //只包含3种，为什么不包含“”红冲预收款核销: 直接把钱退给客户，不退回预收款余额
            switch (paymentSheetTypeEnum) {
                case PREPAYMENT:
                case RED_PREPAYMENT:
                    //红冲预收款存储的是负值可直接使用
                    advancePaymentBalance = data.getDoubleValue(PaymentSheetEnum.AMOUNT.getAttr());
                    break;
                case WRITE_OFF_PREPAYMENT:
                    //预收款核销，核销金额要用余额减去
                    advancePaymentBalance = data.getDoubleValue(PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr());
                    advancePaymentBalance = Arith.mul(advancePaymentBalance,-1D);
                    break;
                case RED_WRITE_OFF_BALANCE:
                    //红冲预收款核销(退到余额)，增加预收款余额
                    advancePaymentBalance = data.getDoubleValue(PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr());
                    advancePaymentBalance = Math.abs(advancePaymentBalance);
                    break;
                default:
                    LOG.error(paymentSheetTypeEnum.getAlias() + PaymentErrorCodeEnum.API_ERROR_208029.getMsg());
                    throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208029);
            }
            Long customerId = data.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr());
            String corpid = paymentSheetEntityExt.getCorpid();
            PaymentBalanceEntity paymentBalanceEntity = paymentBalanceModel.getByCustomerId(customerId, corpid);
            if(paymentBalanceEntity == null){
                if(advancePaymentBalance < 0 ){
                    throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
                }
                paymentBalanceEntity = new PaymentBalanceEntity();
                paymentBalanceEntity.setCorpid(corpid);
                String key = String.format(SymbolConstant.UNDERLINE_PLACE, RedisPrefixConstant.PAYMENT_BALANCE_FORM, distributorMark);
                String value = paasRedisHelper.getValue(key, corpid);
                PaasFormEntityExt paasFormEntity;
                if(StringUtil.isNotEmpty(value)){
                    paasFormEntity = JsonHelperUtil.parseObject(value,PaasFormEntityExt.class);
                }else{
                    paasFormEntity  = paasFormModel.getByBusinessType4Distributor(XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), corpid, distributorMark,"id,app_id,menu_id,distributor_mark");
                    paasRedisHelper.setValue(key, corpid, paasFormEntity, RedisConstant.TINY_DURATION);
                }
                paymentBalanceEntity.setAppId(paasFormEntity.getAppId());
                paymentBalanceEntity.setMenuId(paasFormEntity.getMenuId());
                paymentBalanceEntity.setFormId(paasFormEntity.getId());
                //以下字段来自回款单
                paymentBalanceEntity.setOwnerId(paymentSheetEntityExt.getOwnerId());
                paymentBalanceEntity.setDepartmentId(paymentSheetEntityExt.getDepartmentId());
                paymentBalanceEntity.setCustomerId(customerId);
                paymentBalanceEntity.setAdvancePaymentBalance(advancePaymentBalance);
                paymentBalanceEntity.setCreatorId(paymentSheetEntityExt.getCreatorId());
                long now = DateUtil.getNow();
                paymentBalanceEntity.setAddTime(now);
                paymentBalanceEntity.setUpdateTime(now);
                paymentBalanceEntity.setDel(0);
                Integer insert = paymentBalanceModel.insert(paymentBalanceEntity);
                if(Objects.equals(PaymentBalanceInsertConstant.INSERT,insert)){
                    //插入团队
                    insertBalanceUser(customerId, corpid, paymentBalanceEntity);
                }
                //更新团队  更新不在此处处理  在客户团队更新处处理
            }else{
                if(Arith.add(advancePaymentBalance,paymentBalanceEntity.getAdvancePaymentBalance()) < 0 ){
                    throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
                }
                paymentBalanceEntity.setAdvancePaymentBalance(advancePaymentBalance);
                //删除后的重建
                boolean updateDel = false;
                if(Objects.equals(paymentBalanceEntity.getDel(),1)){
                    paymentBalanceEntity.setDel(0);
                    updateDel = true;
                }
                paymentBalanceModel.update(paymentBalanceEntity,updateDel);
                //删除后的重建
                if(updateDel){
                    insertBalanceUser(customerId, corpid, paymentBalanceEntity);
                }
                //更新团队  更新不在此处处理  在客户团队更新处处理
            }
        } catch (XbbException e) {
            throw  e;
        }catch (Exception e){
            LOG.error(PaymentErrorCodeEnum.API_ERROR_208044.getMsg() ,e);
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208044);
        }
    }

    public void insertBalanceUser(Long customerId, String corpid, PaymentBalanceEntity paymentBalanceEntity) throws XbbException {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(ParameterConstant.CORPID,corpid);
        map.put(BasicConstant.DATAID,customerId);
        map.put(StringConstant.DEL,BasicConstant.ZERO);
        List<CustomerUserEntity> customerUserList = customerUserModel.findEntitys(map);
        if(CollectionsUtil.isNotEmpty(customerUserList)){
            List<PaymentBalanceUserEntity> paymentBalanceUserEntityList = new ArrayList<>(customerUserList.size());
            for (CustomerUserEntity customerUserEntity : customerUserList) {
                PaymentBalanceUserEntity  paymentBalanceUserEntity = new PaymentBalanceUserEntity();
                BeanUtil.copyProperties(customerUserEntity,paymentBalanceUserEntity);
//                        paymentBalanceUserEntity.setId(customerUserEntity.getId());
                paymentBalanceUserEntity.setCustomerId(customerUserEntity.getDataId());
                paymentBalanceUserEntity.setDataId(paymentBalanceEntity.getId());
                paymentBalanceUserEntityList.add(paymentBalanceUserEntity);
            }
            paymentBalanceUserModel.insertBatch(paymentBalanceUserEntityList);
        }
    }

    /**
     * 处理回款单团队
     * @param dataList 回款单data
     * @param corpid 公司id
     * @param sheetTypeEnum
     * @param paymentSheetEntityExt 父回款单
     * @param sheetList 要处理团队的回款单list
     * @param ignoreMainSheet 是否忽略添加父回款单
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void handleSheetTeam(JSONObject dataList, String corpid, SheetTypeEnum sheetTypeEnum, PaymentSheetEntityExt paymentSheetEntityExt, List<PaymentSheetEntityExt> sheetList, boolean ignoreMainSheet) throws XbbException {
        if (ignoreMainSheet) {
            sheetList.add(paymentSheetEntityExt);
        }
        Long customerId = dataList.getLong(PaymentSheetEnum.CUSTOMER_ID.getAttr());
        Map<Long, List<Long>> sheetIdAndDataIdMap = new HashMap<>(sheetList.size());
        List<Long> contractIdIn = new ArrayList<>();
        String attrCon = PaymentSheetEnum.CONTRACT.getAttr();
        for (PaymentSheetEntityExt paymentEntityExt : sheetList){
            fundHelp.handleSheetIdAndContractIdMap(contractIdIn, sheetIdAndDataIdMap, paymentEntityExt, attrCon);
        }
        createPaymentSheetUser(corpid, customerId, contractIdIn, sheetIdAndDataIdMap, sheetTypeEnum, false);
    }

    public BaseVO createPaymentSheetUser(String corpid, Long customerId, List<Long> contractIdIn, Map<Long, List<Long>> sheetIdAndDataIdMap, SheetTypeEnum sheetTypeEnum, Boolean parentNew) throws XbbException {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", corpid);
        map.put("del", DelEnum.NORMAL.getDel());
        List<UserTeamEntity> userTeamList;
        if ( SheetTypeEnum.noBelong(sheetTypeEnum) || parentNew) {
            map.put("customerId", customerId);
            userTeamList = customerUserModel.findBaseEntitys(map);
        } else {
            map.put("contractIdIn", contractIdIn);
            userTeamList = contractUserModel.findBaseEntitys(map);
        }
        Map<Long, UserTypePojo> paySheetIdMap = getSetUserTeamEntityMap(userTeamList,sheetIdAndDataIdMap);

        if (  !paySheetIdMap.isEmpty()) {
            List<PaymentSheetUserEntity> paymentSheetUserEntityList = new ArrayList<>();
            for ( Map.Entry<Long, UserTypePojo> sheetIdAndUser : paySheetIdMap.entrySet() ) {
                Long paymentSheetId = sheetIdAndUser.getKey();
                UserTypePojo userTypePojo = sheetIdAndUser.getValue();
                if ( Objects.nonNull(userTypePojo.getMainUserList()) ) {
                    for ( UserTeamEntity entity : userTypePojo.getMainUserList() ) {
                        PaymentSheetUserEntity paymentSheetUserEntity = new PaymentSheetUserEntity();
                        BeanUtil.copyProperties(entity, paymentSheetUserEntity);
                        paymentSheetUserEntity.setId(null);
                        paymentSheetUserEntity.setIsMain(BasicConstant.MAIN_USER);
                        paymentSheetUserEntity.setDataId(paymentSheetId);
                        paymentSheetUserEntityList.add(paymentSheetUserEntity);
                    }
                }
                if ( Objects.nonNull(userTypePojo.getCoorUserList()) ) {
                    for ( UserTeamEntity entity : userTypePojo.getCoorUserList() ) {
                        PaymentSheetUserEntity paymentSheetUserEntity = new PaymentSheetUserEntity();
                        BeanUtil.copyProperties(entity, paymentSheetUserEntity);
                        paymentSheetUserEntity.setId(null);
                        paymentSheetUserEntity.setIsMain(BasicConstant.COOP_USER);
                        paymentSheetUserEntity.setDataId(paymentSheetId);
                        paymentSheetUserEntityList.add(paymentSheetUserEntity);
                    }
                }
            }
            if ( !paymentSheetUserEntityList.isEmpty() ) {
                paymentSheetUserModel.insertBatch(paymentSheetUserEntityList);
            }
        }
        return new BaseVO();
    }

    private Map<Long, UserTypePojo> getSetUserTeamEntityMap(List<UserTeamEntity> userTeamEntityList, Map<Long, List<Long>> sheetIdAndDataIdMap ){
        Map<Long, UserTypePojo> dataIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (UserTeamEntity userTeamEntity : userTeamEntityList) {
            UserTypePojo userTypePojo = dataIdMap.get(userTeamEntity.getDataId())!=null?dataIdMap.get(userTeamEntity.getDataId()):new UserTypePojo();
            if ( Objects.equals(userTeamEntity.getIsMain(),BasicConstant.MAIN_USER) ){
                userTypePojo.getMainUserList().add(userTeamEntity);
            } else {
                userTypePojo.getCoorUserList().add(userTeamEntity);
            }
            dataIdMap.put(userTeamEntity.getDataId(),userTypePojo);
        }
        Map<Long,UserTypePojo> paySheetIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //todo chenshan需要处理一下在不同合同人上即时负责人又是协同人
        for ( Map.Entry<Long, List<Long>> sheetIdAndDataId : sheetIdAndDataIdMap.entrySet() ) {
            List<Long> dataIds = sheetIdAndDataId.getValue();
            Long paySheetId = sheetIdAndDataId.getKey();
            UserTypePojo newUserTypePojo = new UserTypePojo();
            List<UserTeamEntity> newMainUserList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<UserTeamEntity> newCoorUserList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> userIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for ( Long dataId : dataIds ) {
                UserTypePojo userTypePojo = dataIdMap.get(dataId);
                if ( Objects.nonNull(userTypePojo) ) {
                    List<UserTeamEntity> mainUserList = userTypePojo.getMainUserList();
                    List<UserTeamEntity> coorUserList = userTypePojo.getCoorUserList();
                    for ( UserTeamEntity userTeamEntity : mainUserList ) {
                        if ( !userIdIn.contains(userTeamEntity.getUserId()) ) {
                            newMainUserList.add(userTeamEntity);
                            userIdIn.add(userTeamEntity.getUserId());
                        }
                    }
                    for ( UserTeamEntity userTeamEntity : coorUserList ) {
                        if ( !userIdIn.contains(userTeamEntity.getUserId()) ) {
                            newCoorUserList.add(userTeamEntity);
                        }
                    }
                }
            }
            newUserTypePojo.setMainUserList(newMainUserList);
            newUserTypePojo.setCoorUserList(newCoorUserList);
            paySheetIdMap.put(paySheetId, newUserTypePojo);
        }
        return paySheetIdMap;
    }

    /**
     * 判断前端输入的预收款核销、红冲预收款余额类型回款单的金额是否超过客户余额
     * @param dataList 回款单data
     * @param corpid 公司id
     * @param sheetAmount 回款单金额（红冲预收款余额的红冲金额、预收款核销的核销金额）
     * @throws XbbException
     * @author zcp
     * @date 19/12/10 010 15:42
     * @update 19/12/10 010 15:42
     * @since v1.0
     * @version v1.0
     */
    public void checkCustomerBalance(JSONObject dataList, String corpid, Double sheetAmount) throws XbbException {
        //预收款核销，要控制金额小于客户余额
        Long customerId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, PaymentSheetEnum.CUSTOMER_ID.getAttr(), 0L);
        PaymentBalanceEntity paymentBalanceEntity = paymentBalanceModel.getByCustomerId(customerId, corpid);
        //如果客户预收款余额不足，则不能保存成功
        boolean nonEmptyFlag = paymentBalanceEntity != null && paymentBalanceEntity.getAdvancePaymentBalance() != null;
        boolean over = nonEmptyFlag && Arith.sub(sheetAmount , paymentBalanceEntity.getAdvancePaymentBalance()) > ConfigConstant.amountAccuracy;
        if (over) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_BALANCE_RED);
        }
    }

}
